/**
 ***********************************************************************************************************************
 * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * @file        main.c
 *
 * @brief       User application entry
 *
 * @revision
 * Date         Author          Notes
 * 2020-02-20   OneOS Team      First Version
 ***********************************************************************************************************************
 */
#include <oneos_config.h>
#define DBG_EXT_TAG "NS-LOG"
#define DBG_EXT_LVL DBG_EXT_DEBUG


#include <board.h>
#include <shell.h>
#include <os_dbg_ext.h>
#include <os_sem.h>

#include <fileUtil.h>
#include <ns_auth.h>
#include <ns_text_recog.h>
#include <ns_face_recog.h>
#include <ns_image_recog.h>
#include <ns_text_semantic.h>

#ifdef LOG_EXT_D
#undef LOG_EXT_D
#define LOG_EXT_D printf
#endif

char* MY_TOKEN = OS_NULL;

//Text translation
void _test_text_translation(char* token, char* inputText, enum TEXT_TRANSLATE_TYPE type)
{
    NS_Text_Translation tr_result;
    int ret = ns_text_translation(token, inputText, type, &tr_result);
    if(ret == 0)
    {
        LOG_EXT_D("trans=%s\n", tr_result.translateResult);
        os_free(tr_result.translateResult);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Object detection
void _test_object_detection(char* token, char* filePath, int fileMode)
{
    NS_Object_detection od_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_object_detection_file(token, filePath, &od_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_object_detection(token, contentBuffer, contentSize, &od_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        int count = od_result.objectCount;
        for(int i=0; i<count; i++)
        {
            LOG_EXT_D("object:%d\n", i);
            NS_Object_detection_item* item = od_result.items + i;
            LOG_EXT_D("lable:%d\n", item->objectLabel);
            LOG_EXT_D("score:%f\n", item->score);
            LOG_EXT_D("xmax:%f\n", item->xmax);
            LOG_EXT_D("xmin:%f\n", item->xmin);
            LOG_EXT_D("ymax:%f\n", item->ymax);
            LOG_EXT_D("ymin:%f\n", item->ymin);
        }
        os_free(od_result.items);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Fire detection
void _test_fire_detection(char* token, char* filePath, int fileMode)
{
    NS_Fire_Detection fr_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_fire_detection_file(token, filePath, &fr_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_fire_detection(token, contentBuffer, contentSize, &fr_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("Fire probability:%f, No fire probability:%f\n", fr_result.fire, fr_result.nofire);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Mask detection
void _test_mask_detection(char* token, char* filePath, int fileMode)
{
    NS_Mask_Detection mk_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_mask_detection_file(token, filePath, &mk_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_mask_detection(token, contentBuffer, contentSize, &mk_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("Object count:%d\n", mk_result.objectCount);
        for(int i=0; i<mk_result.objectCount; i++)
        {
            LOG_EXT_D("Object_%d: have_mask:%d\n", i, *((mk_result.haveMask)+i));
            LOG_EXT_D("Coordinate:%s\n", *((mk_result.coordinates)+i));
            os_free(*((mk_result.coordinates)+i));
        }

        os_free(mk_result.haveMask);
        os_free(mk_result.coordinates);

        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Image violation
void _test_violation_detection(char* token, char* filePath, int fileMode)
{
    NS_Violation_Detection vo_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_violation_detection_file(token, filePath, &vo_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_violation_detection(token, contentBuffer, contentSize, &vo_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("No violation:%d\n", vo_result.noviolation);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Face detection
void _test_face_detection(char* token, char* filePath, int fileMode)
{
    NS_Face_Detection fd_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_face_detection_file(token, filePath, &fd_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_face_detection(token, contentBuffer, contentSize, &fd_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("Face detection number:%d\n", fd_result.faceNumber);
        for(int i=0; i<fd_result.faceNumber; i++)
        {
            LOG_EXT_D("Face rect:%s\n", *(fd_result.faceRect + i));
        }

        for(int i=0; i<fd_result.faceNumber; i++)
        {
            LOG_EXT_D("free:%d\n", i);
            os_free(*(fd_result.faceRect + i));
        }
        os_free(fd_result.faceRect);

        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Face Location
void _test_face_location(char* token, char* filePath, int fileMode)
{
    NS_Face_Location fl_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_face_location_file(token, filePath, &fl_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_face_location(token, contentBuffer, contentSize, &fl_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("Face location number:%d\n", fl_result.faceNumber);

        for(int i = 0; i< fl_result.faceNumber; i++)
        {
            LOG_EXT_D("face %d \n", i);
            for(int j =0; j<*(fl_result.facePointCount+i); j++)
            {
                LOG_EXT_D("point:%s\n", *(*(fl_result.faceLocation+i)+j));
            }
            LOG_EXT_D("----------------------");
        }

        //free
        for(int i = 0; i< fl_result.faceNumber; i++)
        {
            char** point_array = *(fl_result.faceLocation+i);
            int point_count = *(fl_result.facePointCount+i);
            LOG_EXT_D("free face %d, point:%d \n", i, point_count);

            for(int j =0; j < point_count; j++)
            {
                os_free(*(point_array + j)); //free point string
            }

            os_free(point_array); //free point array
            LOG_EXT_D("----------------------");
        }
        os_free(fl_result.faceLocation);
        os_free(fl_result.facePointCount);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Face Property
void _test_face_property(char* token, char* filePath, int fileMode)
{
    NS_Face_Property fp_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_face_property_file(token, filePath, &fp_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_face_property(token, contentBuffer, contentSize, &fp_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        for (int i = 0; i < fp_result.faceNumber; i++) {
            NS_Face_Property_Item* item = fp_result.items + i;
            LOG_EXT_D("Face %d: age=%d, expression=%s, gender=%s, race=%s\n", i, item->age, item->expression, item->gender, item->race);
        }

        os_free(fp_result.items);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Human Property
void _test_human_property(char* token, char* filePath, int fileMode)
{
    NS_Human_Property hp_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_human_property_file(token, filePath, &hp_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_human_property(token, contentBuffer, contentSize, &hp_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        for (int i = 0; i < hp_result.personNumber; i++) {
            NS_Human_Property_Item* item = hp_result.items + i;
            LOG_EXT_D("Human %d: age=%s, isFemale=%s, glasses=%s, upType=%s\n", i, item->age, item->isFemale, item->glasses, item->upType);
        }

        os_free(hp_result.items);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Invoice
void _test_invoice_recog(char* token, char* filePath, int fileMode)
{
    NS_Invoice invoice_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_invoice_recog_file(token, filePath, &invoice_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_invoice_recog(token, contentBuffer, contentSize, &invoice_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("invoiceCode:%s\n", invoice_result.invoiceCode);

        LOG_EXT_D("invoiceNumber:%s\n", invoice_result.invoiceNumber);
        LOG_EXT_D("invoiceDate:%s\n", invoice_result.invoiceDate);
        LOG_EXT_D("invoiceAmount:%s\n", invoice_result.invoiceAmount);
        LOG_EXT_D("capitalAmount:%s\n", invoice_result.capitalAmount);

        LOG_EXT_D("buyerName:%s\n", invoice_result.buyerName);
        LOG_EXT_D("buyerTaxNumber:%s\n", invoice_result.buyerTaxNumber);
        LOG_EXT_D("sellerName:%s\n", invoice_result.sellerName);
        LOG_EXT_D("sellerTaxNumber:%s\n", invoice_result.sellerTaxNumber);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Id card
void _test_id_card_recog(char* token, char* filePath, int fileMode)
{
    NS_Id_Card id_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_id_card_recog_file(token, filePath, &id_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_id_card_recog(token, contentBuffer, contentSize, &id_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("address:%s\n", id_result.address);
        LOG_EXT_D("authority:%s\n", id_result.authority);
        LOG_EXT_D("birthday:%s\n", id_result.birthday);
        LOG_EXT_D("effectiveDate:%s\n", id_result.effectiveDate);

        LOG_EXT_D("ethnicity:%s\n", id_result.ethnicity);
        LOG_EXT_D("expiryDate:%s\n", id_result.expiryDate);
        LOG_EXT_D("gender:%s\n", id_result.gender);
        LOG_EXT_D("idNumber:%s\n", id_result.idNumber);

        LOG_EXT_D("name:%s\n", id_result.name);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Id card
void _test_vehicle_plate_recog(char* token, char* filePath, int fileMode)
{
    NS_Vehicle_Plate vp_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_vehicle_plate_recog_file(token, filePath, &vp_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_vehicle_plate_recog(token, contentBuffer, contentSize, &vp_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("car no:%s\n", vp_result.carNumber);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//Bank card
void _test_bank_card_recog(char* token, char* filePath, int fileMode)
{
    NS_Bank_Card bank_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_bank_card_recog_file(token, filePath, &bank_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_bank_card_recog(token, contentBuffer, contentSize, &bank_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("bank no:%s\n", bank_result.cardNumber);
        LOG_EXT_D("exp date:%s\n", bank_result.expiryDate);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//OCR
void _test_ocr_recog(char* token, char* filePath, int fileMode)
{
    NS_OCR ocr_result;

    int ret = -1;
    if (fileMode) {
        ret = ns_ocr_recog_file(token, filePath, &ocr_result);
    } else {
        long contentSize = 0;
        char* contentBuffer = read_file_all(filePath, &contentSize);
        ret = ns_ocr_recog(token, contentBuffer, contentSize, &ocr_result);
        os_free(contentBuffer);
    }

    if(ret == 0)
    {
        LOG_EXT_D("item count:%d\n", ocr_result.ocrItemCount);
        for (int i = 0; i < ocr_result.ocrItemCount; i++) {
            NS_OCR_Item* item = ocr_result.items + i;
            LOG_EXT_D("<%d>:%s\n", i, item->word);
            LOG_EXT_D("location:%d, %d, %d, %d\n", item->x1, item->x2, item->y1, item->y2);
            os_free(item->word);
        }
        os_free(ocr_result.items);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

//-------------------------------------------------------------------------------//
void test_object_detection()
{
    _test_object_detection(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 1);
    os_task_mdelay(2000);
    _test_object_detection(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 0);
}

void test_fire_detection()
{
    _test_fire_detection(MY_TOKEN, "/sdcard/jiutian/fire_detect.jpg", 1);
    os_task_mdelay(2000);
    _test_fire_detection(MY_TOKEN, "/sdcard/jiutian/fire_detect.jpg", 0);
}

void test_mask_detection()
{
    _test_mask_detection(MY_TOKEN, "/sdcard/jiutian/mask_detect.jpg", 1);
    os_task_mdelay(2000);
    _test_mask_detection(MY_TOKEN, "/sdcard/jiutian/mask_detect.jpg", 0);
}

void test_violation_detection()
{
    _test_violation_detection(MY_TOKEN, "/sdcard/jiutian/face_prop.jpg", 1);
    os_task_mdelay(2000);
    _test_violation_detection(MY_TOKEN, "/sdcard/jiutian/face_prop.jpg", 0);
}

void test_face_detection()
{
    _test_face_detection(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 1);
    os_task_mdelay(2000);
    _test_face_detection(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 0);
}

void test_face_location()
{
    _test_face_location(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 1);
    os_task_mdelay(2000);
    _test_face_location(MY_TOKEN, "/sdcard/jiutian/face_detect2.jpg", 0);
}

void test_face_property()
{
    _test_face_property(MY_TOKEN, "/sdcard/jiutian/face_prop.jpg", 1);
    os_task_mdelay(2000);
    _test_face_property(MY_TOKEN, "/sdcard/jiutian/face_prop.jpg", 0);
}

void test_human_property()
{
    _test_human_property(MY_TOKEN, "/sdcard/jiutian/body_prop.jpg", 1);
    os_task_mdelay(2000);
    _test_human_property(MY_TOKEN, "/sdcard/jiutian/body_prop.jpg", 0);
}

void test_invoice_recog()
{
    _test_invoice_recog(MY_TOKEN, "/sdcard/jiutian/invoice.jpg", 1);
    os_task_mdelay(2000);
    _test_invoice_recog(MY_TOKEN, "/sdcard/jiutian/invoice.jpg", 0);
}

void test_id_card_recog()
{
    _test_id_card_recog(MY_TOKEN, "/sdcard/jiutian/id-mid.jpg", 1);
    os_task_mdelay(2000);
    _test_id_card_recog(MY_TOKEN, "/sdcard/jiutian/id-mid.jpg", 0);
}

void test_vehicle_plate_recog()
{
    _test_vehicle_plate_recog(MY_TOKEN, "/sdcard/jiutian/car-mid.jpg", 1);
    os_task_mdelay(2000);
    _test_vehicle_plate_recog(MY_TOKEN, "/sdcard/jiutian/car-mid.jpg", 0);
}

void test_bank_card_recog()
{
    _test_bank_card_recog(MY_TOKEN, "/sdcard/jiutian/bank-sample.jpg", 1);
    os_task_mdelay(2000);
    _test_bank_card_recog(MY_TOKEN, "/sdcard/jiutian/bank-sample.jpg", 0);
}

void test_ocr_recog()
{
    _test_ocr_recog(MY_TOKEN, "/sdcard/jiutian/ocr_text.jpg", 1);
    os_task_mdelay(2000);
    _test_ocr_recog(MY_TOKEN, "/sdcard/jiutian/ocr_text.jpg", 0);
}

void test_text_translation()
{
    _test_text_translation(MY_TOKEN, "中国人民站起来了", NS_TRANS_CHN_TO_ENG);
    os_task_mdelay(2000);
    _test_text_translation(MY_TOKEN, "You can not find yourself, you can only establish yourself.", NS_TRANS_ENG_TO_CHN);
}

void test_text_classification()
{
    NS_Text_Classification tc_result;
    int ret = ns_text_classification(MY_TOKEN, "星星点灯", &tc_result);
    if(ret == 0)
    {
        LOG_EXT_D("type=%s\n", tc_result.kind);
        os_free(tc_result.kind);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

void test_text_keyword()
{
    NS_Text_Keyword result;
    int ret = ns_text_keyword(MY_TOKEN, "人的一生，其实就是一段具有体验性的时间", &result);
    if(ret == 0)
    {
        LOG_EXT_D("count=%d\n", result.keywordNumber);
        for(int i = 0; i< result.keywordNumber; i++)
        {
            LOG_EXT_D("word<%d>:%s\n", i, (result.items + i)->word);
            LOG_EXT_D("weight=%f\n", (result.items + i)->weight);
            os_free((result.items + i)->word);
        }
        os_free(result.items);
        LOG_EXT_D("pass >>>\n");
        return;
    }

    LOG_EXT_D("fail >>>\n");
}

int main(void)
{
    init_sd_card("sd0", "/", "fat");

    //request token
    char* token = os_malloc(100);

    char* token_path = "/sdcard/jiutian/mytoken";
    int token_fd = open(token_path, O_RDONLY);
    if(token_fd < 0)
    {
        LOG_EXT_D("no token file yet, get token now\n");

        int ret = ns_get_auth_token(token);

        if(ret != OS_EOK)
        {
            LOG_EXT_E("fail to get token\n");
            return -OS_ERROR;
        }
        LOG_EXT_D("Get Token:%s, len:%d\n", token, strlen(token));

        //save token
        token_fd = open(token_path, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
        if(token_fd < 0)
        {
            LOG_EXT_E("fail to create token file\n");
            return -OS_ERROR;
        }
        write(token_fd, token, strlen(token)+1);
        close(token_fd);
    }
    else
    {
        LOG_EXT_D("token file exist, read token now\n");
        read(token_fd, token, 100);
        LOG_EXT_D("read token back:%s\n", token);
    }

    //set token
    MY_TOKEN = token;

    while(1)
    {
        os_task_mdelay(1000);
    }

    return 0;
}


SH_CMD_EXPORT(test_face_detection, test_face_detection, "face detection");
SH_CMD_EXPORT(test_face_location, test_face_location, "face location");
SH_CMD_EXPORT(test_face_property, test_face_property, "face property");
SH_CMD_EXPORT(test_human_property, test_human_property, "human property");

SH_CMD_EXPORT(test_invoice_recog, test_invoice_recog, "invoice recognition");
SH_CMD_EXPORT(test_id_card_recog, test_id_card_recog, "id card recognition");
SH_CMD_EXPORT(test_vehicle_plate_recog, test_vehicle_plate_recog, "vehicle plate recognition");
SH_CMD_EXPORT(test_bank_card_recog, test_bank_card_recog, "bank card recognition");
SH_CMD_EXPORT(test_ocr_recog, test_ocr_recog, "ocr text recognition");

SH_CMD_EXPORT(test_fire_detection, test_fire_detection, "fire detection");
SH_CMD_EXPORT(test_mask_detection, test_mask_detection, "mask detection");
SH_CMD_EXPORT(test_violation_detection, test_violation_detection, "violation detection");
SH_CMD_EXPORT(test_object_detection, test_object_detection, "object detection");

SH_CMD_EXPORT(test_text_translation, test_text_translation, "text translation");
SH_CMD_EXPORT(test_text_classification, test_text_classification, "text classification");
SH_CMD_EXPORT(test_text_keyword, test_text_keyword, "text keyword");
